home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / pvm34b3.zip / pvm34b3 / pvm3 / src / imalloc.c < prev    next >
C/C++ Source or Header  |  1997-07-22  |  13KB  |  556 lines

  1.  
  2. static char rcsid[] =
  3.     "$Id: imalloc.c,v 1.4 1997/06/25 22:08:48 pvmsrc Exp $";
  4.  
  5. /*
  6.  *         PVM version 3.4:  Parallel Virtual Machine System
  7.  *               University of Tennessee, Knoxville TN.
  8.  *           Oak Ridge National Laboratory, Oak Ridge TN.
  9.  *                   Emory University, Atlanta GA.
  10.  *      Authors:  J. J. Dongarra, G. E. Fagg, M. Fischer
  11.  *          G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci,
  12.  *         P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam
  13.  *                   (C) 1997 All Rights Reserved
  14.  *
  15.  *                              NOTICE
  16.  *
  17.  * Permission to use, copy, modify, and distribute this software and
  18.  * its documentation for any purpose and without fee is hereby granted
  19.  * provided that the above copyright notice appear in all copies and
  20.  * that both the copyright notice and this permission notice appear in
  21.  * supporting documentation.
  22.  *
  23.  * Neither the Institutions (Emory University, Oak Ridge National
  24.  * Laboratory, and University of Tennessee) nor the Authors make any
  25.  * representations about the suitability of this software for any
  26.  * purpose.  This software is provided ``as is'' without express or
  27.  * implied warranty.
  28.  *
  29.  * PVM version 3 was funded in part by the U.S. Department of Energy,
  30.  * the National Science Foundation and the State of Tennessee.
  31.  */
  32.  
  33. /*
  34.  *    imalloc.c
  35.  *
  36.  *    Instrumented malloc filter.
  37.  *
  38.  *    7 Jun 1991  Robert Manchek  manchek@CS.UTK.EDU.
  39.  *    6 Sep 1991  added static glob and check features.
  40.  *    17 Dec 1991 added i_realloc, cleaned up.
  41.  *    8 Sep 1992  added total byte count.
  42.  *    30 Oct 1992 added object type tag
  43.  *
  44.  *    To use, add something like the following to your code:
  45.  *        #define malloc(n) i_malloc(n)
  46.  *        #define realloc(p,n) i_realloc(p,n)
  47.  *        #define free(p) i_free(p)
  48.  *    recompile, and link.
  49.  *
  50.  *    Facilities:
  51.  *
  52.  *    $ All errors written to fd 2 (not using stdio).
  53.  *
  54.  *    $ Configurable to die on error for debugger.
  55.  *        Define DIEONERROR as 0 or 1.
  56.  *
  57.  *    $ Configurable to use statically allocated space for recordkeeping.
  58.  *        This makes imalloc more immune to bad heap space trashing.
  59.  *        Define STATICGLOBS as nonzero.
  60.  *
  61.  *    $ I_malloc():
  62.  *        Error on [adjustable] unreasonble length or malloc() failed.
  63.  *        Hashes descriptors of all chunks for i_free() checking.
  64.  *        Numbers requests to indicate order received.
  65.  *        Writes [adjustable] pseudo-random head and tail pads to
  66.  *            aid in checking overrun of chunk.
  67.  *
  68.  *    $ I_free(ptr):
  69.  *        Error if chunk not i_malloc()d.
  70.  *        Checks head and tail pads.
  71.  *        [Optionally] zeros chunk to aid in detecting late use.
  72.  *        Define ZEROONFREE as 0 or 1.
  73.  *
  74.  *    $ I_dump(how):
  75.  *        Callable from user program.
  76.  *        Dumps the hash table to see what chunks are active.
  77.  *        If how is 1, checks each chunk's head and tail pads.
  78.  *
  79.  */
  80.  
  81. #ifdef    HASSTDLIB
  82. #include <stdlib.h>
  83. #endif
  84. #include <stdio.h>
  85. #ifdef    SYSVSTR
  86. #include <string.h>
  87. #else
  88. #include <strings.h>
  89. #endif
  90. /*
  91. #include <malloc.h>  XXX fails on next
  92. */
  93. #include "bfunc.h"
  94.  
  95. #ifndef    DIEONERROR
  96. #define    DIEONERROR    1
  97. #endif
  98. #ifndef    ZEROONFREE
  99. #define    ZEROONFREE    1
  100. #endif
  101. #ifndef    STATICGLOBS
  102. #define    STATICGLOBS    0
  103. #endif
  104. #ifndef    DUMPHDR
  105. #define    DUMPHDR    "i_dump()"
  106. #endif
  107. #ifndef    LET0BE1
  108. #define    LET0BE1    1
  109. #endif
  110.  
  111. #define    NEXTRN(x)    (x = (x) + (x) + (((x ^ (x >> 3)) & 0x2000) ? 1 : 0))
  112. #define    HASH(p)        (((long)(p) ^ ((long)(p) >> 8) ^ ((long)(p) >> 16) ^ ((long)(p) >> 24)) & 0xff)
  113.  
  114. /* write a null-term string */
  115.  
  116. #if 0
  117. #define SWRITE(fd,s) write((fd),(s),strlen(s))
  118. #endif
  119. #define SWRITE(fd,s) pvmlogerror(s)
  120.  
  121. /* this describes a chunk of memory */
  122.  
  123. struct glob {
  124.     struct glob *next;    /* next glob in hash bucket */
  125.     char *base;            /* baseaddr of user chunk */
  126.     int len;            /* len of user chunk */
  127.     int id;                /* chunk id */
  128.     int lop;            /* nbytes head padding */
  129.     int hip;            /* nbytes tail padding */
  130.     int rst;            /* starting random state */
  131.     int flg;
  132.     char tag[4];        /* content tag */
  133. };
  134.  
  135. #define    OBALLOC        1    /* ob was just alloced - cleared by dump() */
  136. #define    OBREALLOC    2    /* ob was just realloced - cleared by dump() */
  137.  
  138.  
  139. /* default values */
  140.  
  141. #if 0
  142. static int debfd = 2;                /* debug file descriptor */
  143. #endif
  144. static int lengthlimit = 1048576;    /* max length malloc allowed */
  145. static int lopad = 16;                /* chunk head pad */
  146. static int hipad = 16;                /* chunk tail pad */
  147.  
  148. /* globals */
  149.  
  150. static int totlnbyts = 0;            /* total bytes allocated */
  151. static int rnstate = 1;                /* random sequence gen. */
  152. static struct glob *hashtbl[256];    /* chunk hash table */
  153. static char msbuf[256];                /* error message buffer */
  154. static int firsttime = 1;
  155. static int globid = 0;                /* chunk id counter */
  156. #if    STATICGLOBS > 0
  157. static struct glob globheap[STATICGLOBS];
  158. static struct glob *globfl = 0;
  159. static int globavail = STATICGLOBS;
  160. #endif
  161.  
  162.  
  163. /*    i_choke()
  164. *
  165. *    Found an inconsistency; bail.
  166. */
  167.  
  168. void
  169. i_choke()
  170. {
  171. #if    DIEONERROR
  172.     abort();
  173. #endif
  174. }
  175.  
  176.  
  177. /*    i_malloc()
  178. *
  179. *    Allocate a buffer of given length.
  180. */
  181.  
  182. char*
  183. i_malloc(len, tag)
  184.     unsigned len;    /* number of bytes */
  185.     char *tag;        /* content description */
  186. {
  187.     char *ptr;
  188.     struct glob *ob;    /* hash tbl entry */
  189.     struct glob **he;
  190.     int i;                /* gp */
  191.  
  192.     if (firsttime) {
  193.         firsttime = 0;
  194.         BZERO((char*)hashtbl, sizeof(hashtbl));
  195.  
  196. #if    STATICGLOBS > 0
  197.     /* initialize the glob freelist */
  198.         ob = 0;
  199.         for (i = STATICGLOBS-1; i >= 0; i--) {
  200.             globheap[i].next = ob;
  201.             ob = &globheap[i];
  202.         }
  203.         globfl = ob;
  204. #endif
  205.     }
  206.  
  207.     /* check req length */
  208.  
  209. #if LET0BE1 > 0
  210.     if (!len)
  211.         len = 1;
  212. #endif
  213.     if (len < 1 || len > lengthlimit) {
  214.         (void)sprintf(msbuf, "i_malloc: bogus len=%d\n", len);
  215.         (void)SWRITE(debfd, msbuf);
  216.         i_choke();
  217.         return (char*)0;
  218.     }
  219.  
  220.     /* do actual malloc */
  221.  
  222.     if (!(ptr = (char*)malloc(len + lopad + hipad))) {
  223.         (void)sprintf(msbuf, "i_malloc: malloc failed len=%d\n", len);
  224.         (void)SWRITE(debfd, msbuf);
  225.         i_choke();
  226.         return (char*)0;
  227.     }
  228.  
  229.     /* get descriptor */
  230.  
  231. #if STATICGLOBS > 0
  232.     if (ob = globfl) {
  233.         globfl = globfl->next;
  234.         globavail--;
  235.  
  236.     } else {
  237.         (void)sprintf(msbuf, "i_malloc: glob allocate failed (max %d)\n",
  238.             STATICGLOBS);
  239.         (void)SWRITE(debfd, msbuf);
  240.         i_choke();
  241.         return (char*)0;
  242.     }
  243. #else
  244.     if (!(ob = (struct glob*)malloc(sizeof(struct glob)))) {
  245.         (void)sprintf(msbuf, "i_malloc: malloc failed for glob\n");
  246.         (void)SWRITE(debfd, msbuf);
  247.         i_choke();
  248.         return (char*)0;
  249.     }
  250. #endif
  251.  
  252.     /* enter descriptor, write head and tail pads */
  253.  
  254.     ob->flg = OBALLOC;
  255.     ob->id = ++globid;
  256.     ob->tag[0] = 0;
  257.     if (tag)
  258.         strncpy(ob->tag, tag, 4);
  259.     ob->len = len;
  260.     ob->lop = lopad;
  261.     ob->hip = hipad;
  262.     ob->rst = rnstate;
  263.     for (i = lopad; i-- > 0; *ptr++ = NEXTRN(rnstate));
  264.     ob->base = ptr;
  265.     he = &hashtbl[HASH(ptr)];
  266.     for (i = hipad, ptr += len; i-- > 0; *ptr++ = NEXTRN(rnstate));
  267.     ob->next = *he;
  268.     *he = ob;
  269.     totlnbyts += len;
  270.     return ob->base;
  271. }
  272.  
  273.  
  274. /*    i_free()
  275. *
  276. *    Give up a previously allocated buffer.
  277. */
  278.  
  279. i_free(loc)
  280.     char *loc;        /* ptr to buffer */
  281. {
  282.     struct glob *ob;    /* freeing this object */
  283.     struct glob *preob;    /* object before in chain */
  284.     int rs;                /* reproduced random seqn */
  285.     char *ptr = loc;    /* gp */
  286.     struct glob **he;    /* hash tbl entry */
  287.     int i;                /* gp */
  288.  
  289.     /* sanity check */
  290.  
  291.     if (firsttime) {
  292.         char *s = "i_free: called before i_malloc?\n";
  293.         SWRITE(debfd, s);
  294.         i_choke();
  295.         return 0;
  296.     }
  297.  
  298.     /* delete from hash tbl */
  299.  
  300.     he = &hashtbl[HASH(loc)];
  301.     for (preob = 0, ob = *he; ob && ob->base != loc; preob = ob, ob = ob->next);
  302.     if (!ob) {
  303.         (void)sprintf(msbuf, "i_free: bogus loc=0x%x\n", loc);
  304.         (void)SWRITE(debfd, msbuf);
  305.         i_choke();
  306.         return 0;
  307.     }
  308.     rs = ob->rst;
  309.  
  310.     /* check head and tail pads */
  311.  
  312.     for (i = ob->lop, ptr -= i; i > 0; i--)
  313.         if ((0xff & (int)(*ptr++)) != (0xff & NEXTRN(rs))) {
  314.             (void)sprintf(msbuf, "i_free: scribbled in 0x%x[%d]\n", loc, -i);
  315.             (void)SWRITE(debfd, msbuf);
  316.             i_choke();
  317.         }
  318.     for (i = ob->hip, ptr += ob->len; i > 0; i--)
  319.         if ((0xff & (int)(*ptr++)) != (0xff & NEXTRN(rs))) {
  320.             (void)sprintf(msbuf, "i_free: scribbled in 0x%x[%d+%d]\n",
  321.                 loc, ob->len, ob->hip - i);
  322.             (void)SWRITE(debfd, msbuf);
  323.             i_choke();
  324.         }
  325.  
  326.     /* do actual free */
  327.  
  328. #if    ZEROONFREE
  329.     BZERO(loc - ob->lop, ob->len + ob->lop + ob->hip);
  330. #endif
  331.     free(loc - ob->lop);
  332.     totlnbyts -= ob->len;
  333.  
  334.     /* reclaim descriptor */
  335.  
  336.     if (preob)
  337.         preob->next = ob->next;
  338.     else
  339.         *he = ob->next;
  340. #if STATICGLOBS > 0
  341.     ob->next = globfl;
  342.     globfl = ob;
  343.     globavail++;
  344. #else
  345.     free((char*)ob);
  346. #endif
  347.     return 0;
  348. }
  349.  
  350.  
  351. /*    i_realloc()
  352. *
  353. *    Resize a previously allocated buffer (possibly relocate as well)
  354. *    and leave the contents unchanged up to the minimum of the old
  355. *    and new lengths.
  356. */
  357.  
  358. char*
  359. i_realloc(loc, len)
  360.     char *loc;            /* old buffer */
  361.     unsigned len;        /* length of new buffer */
  362. {
  363.     struct glob *ob;    /* freeing this object */
  364.     struct glob *preob;    /* object before in chain */
  365.     int rs;                /* reproduced random seqn */
  366.     char *ptr = loc;    /* gp */
  367.     struct glob **he;    /* hash tbl entry */
  368.     int i;                /* gp */
  369.  
  370.     /* sanity check */
  371.  
  372.     if (firsttime) {
  373.         char *s = "i_realloc: called before i_malloc?\n";
  374.         SWRITE(debfd, s);
  375.         i_choke();
  376.         return (char*)0;
  377.     }
  378.  
  379.     /* check req length */
  380.  
  381. #if LET0BE1 > 0
  382.     if (!len)
  383.         len = 1;
  384. #endif
  385.     if (len < 1 || len > lengthlimit) {
  386.         (void)sprintf(msbuf, "i_realloc: bogus len=%d\n", len);
  387.         (void)SWRITE(debfd, msbuf);
  388.         i_choke();
  389.         return (char*)0;
  390.     }
  391.  
  392.     /* delete from hash tbl */
  393.  
  394.     he = &hashtbl[HASH(loc)];
  395.     for (preob = 0, ob = *he; ob && ob->base != loc; preob = ob, ob = ob->next);
  396.     if (!ob) {
  397.         (void)sprintf(msbuf, "i_realloc: bogus loc=0x%x\n", loc);
  398.         (void)SWRITE(debfd, msbuf);
  399.         i_choke();
  400.         return (char*)0;
  401.     }
  402.     rs = ob->rst;
  403.  
  404.     /* check head and tail pads */
  405.  
  406.     for (i = ob->lop, ptr -= i; i > 0; i--)
  407.         if ((0xff & (int)(*ptr++)) != (0xff & NEXTRN(rs))) {
  408.             (void)sprintf(msbuf, "i_realloc: scribbled in 0x%x[%d]\n", loc, -i);
  409.             (void)SWRITE(debfd, msbuf);
  410.             i_choke();
  411.         }
  412.     for (i = ob->hip, ptr += ob->len; i > 0; i--)
  413.         if ((0xff & (int)(*ptr++)) != (0xff & NEXTRN(rs))) {
  414.             (void)sprintf(msbuf, "i_realloc: scribbled in 0x%x[%d+%d]\n",
  415.                 loc, ob->len, ob->hip - i);
  416.             (void)SWRITE(debfd, msbuf);
  417.             i_choke();
  418.         }
  419.  
  420.     /* remove descriptor */
  421.  
  422.     if (preob)
  423.         preob->next = ob->next;
  424.     else
  425.         *he = ob->next;
  426.  
  427.     /* realloc */
  428.  
  429.     if (!(ptr = (char*)realloc(loc - ob->lop, len + lopad + hipad))) {
  430.         (void)sprintf(msbuf, "i_realloc: malloc failed len=%d\n", len);
  431.         (void)SWRITE(debfd, msbuf);
  432.         i_choke();
  433.         return (char*)0;
  434.     }
  435.  
  436.     /* rewrite descriptor, write head and tail pads */
  437.  
  438.     totlnbyts += len - ob->len;
  439.     ob->flg = OBREALLOC;
  440.     ob->id = ++globid;    /* XXX ? */
  441.     ob->len = len;
  442.     ob->lop = lopad;
  443.     ob->hip = hipad;
  444.     ob->rst = rnstate;
  445.     for (i = lopad; i-- > 0; *ptr++ = NEXTRN(rnstate));
  446.     ob->base = ptr;
  447.     he = &hashtbl[HASH(ptr)];
  448.     for (i = hipad, ptr += len; i-- > 0; *ptr++ = NEXTRN(rnstate));
  449.     ob->next = *he;
  450.     *he = ob;
  451.     return ob->base;
  452. }
  453.  
  454.  
  455. /*    ascdump()
  456. *
  457. *    Convert byte string to printable characters.
  458. */
  459.  
  460. static void
  461. ascdump(o, p, e)
  462.     char **o;        /* addr of pointer to output space (passed back) */
  463.     char *p;        /* string to convert */
  464.     int e;            /* length of string */
  465. {
  466.     char *r = *o;
  467.     char c;
  468.  
  469.     while (e-- > 0) {
  470.         c = 0x7f & *p;
  471.         if (c < ' ' || c == 0x7f) {
  472.             c = (c + '@') & 0x7f;
  473.             *r++ = '^';
  474.         } else
  475.             *r++ = ' ';
  476.         *r++ = c;
  477.         p++;
  478.     }
  479.     *r++ = '\n';
  480.     *r = 0;
  481.     *o = r;
  482. }
  483.  
  484.  
  485. /*    i_dump()
  486. *
  487. *    Dump the table of contents of allocated buffers.
  488. */
  489.  
  490. void
  491. i_dump(how)
  492.     int how;            /* != 0 also do sanity checking */
  493. {
  494.     int ht;                /* hash table index */
  495.     struct glob *ob;
  496.     char *r;
  497.     int i;
  498.     int rs;                /* reproduced random seqn */
  499.     char *ptr;            /* gp */
  500.     int err;
  501.     char tagstr[5];
  502.  
  503. #if    STATICGLOBS > 0
  504.     sprintf(msbuf, "%s %d bytes total/%d globs free\n",
  505.             DUMPHDR, totlnbyts, globavail);
  506.     (void)SWRITE(debfd, msbuf);
  507. #else
  508.     sprintf(msbuf, "%s %d bytes total\n", DUMPHDR, totlnbyts);
  509.     (void)SWRITE(debfd, msbuf);
  510. #endif
  511.     for (ht = 0; ht < 256; ht++) {
  512.         for (ob = hashtbl[ht]; ob; ob = ob->next) {
  513.             rs = ob->rst;
  514.             ptr = ob->base;
  515.             err = 0;
  516.             if (how) {
  517.                 for (i = ob->lop, ptr -= i; i > 0; i--)
  518.                     if ((0xff & (int)(*ptr++)) != (0xff & NEXTRN(rs))) {
  519.                         (void)sprintf(msbuf,
  520.                             "%5d 0x%08x[%d]: scribbled in [%d]\n",
  521.                             ob->id, ob->base, ob->len, -i);
  522.                         (void)SWRITE(debfd, msbuf);
  523.                         err++;
  524.                     }
  525.                 for (i = ob->hip, ptr += ob->len; i > 0; i--)
  526.                     if ((0xff & (int)(*ptr++)) != (0xff & NEXTRN(rs))) {
  527.                         (void)sprintf(msbuf,
  528.                             "%5d 0x%08x[%d]: scribbled in [%d+%d]\n",
  529.                             ob->id, ob->base, ob->len, ob->len, ob->hip - i);
  530.                         (void)SWRITE(debfd, msbuf);
  531.                         err++;
  532.                     }
  533.             }
  534.             if (!err) {
  535.                 strncpy(tagstr, ob->tag, 4);
  536.                 tagstr[4] = 0;
  537.                 sprintf(msbuf, "%5d%c%4s 0x%08x[%4d]",
  538.                     ob->id,
  539.                     (ob->flg & OBALLOC ? '*' :
  540.                         (ob->flg & OBREALLOC ? '+' : ' ')),
  541.                     tagstr,
  542.                     ob->base, ob->len);
  543.                 r = msbuf + strlen(msbuf);
  544.                 *r++ = ' ';
  545.                 if ((i = ob->len) > 24)
  546.                     i = 24;
  547.                 ascdump(&r, ob->base, i);
  548.                 (void)SWRITE(debfd, msbuf);
  549.             }
  550.             ob->flg &= ~(OBALLOC|OBREALLOC);
  551.         }
  552.     }
  553. }
  554.  
  555.  
  556.